File Input
Allows users to select and upload files from their devices. Used in forms, applications, or processes where user-provided files are necessary.
#Examples
#Default
The standard way to let users upload a single file. It shows a button that triggers the device's file selection dialog. After selection, displays the chosen file name.
const [files, setFiles] = useState<FileList | null>(null);
return (
<FileInput value={files} onChange={(x: FileList | null) => setFiles(x)}>
Choose file
</FileInput>
);
#Don't List Files
Ideal when file names are irrelevant to the user's task.
const [files, setFiles] = useState<FileList | null>(null);
useEffect(() => {
console.log(files);
}, [files]);
return (
<FileInput listFiles={false} value={files} onChange={(x: FileList | null) => setFiles(x)}>
Choose file
</FileInput>
);
#Hide Button
Best Practice:
- Embed the input within a custom element.
- Visually indicate the upload zone with clear instructions and cues.
const [files, setFiles] = useState<FileList | null>(null);
const hasFiles = files != undefined && files != null && files.length > 0;
return (
<FileInput hideButton={hasFiles} value={files} onChange={(x: FileList | null) => setFiles(x)}>
Choose file
</FileInput>
);
#Multiple Files
When users need to upload multiple files at once.
Best Practice:
- Allow users to select several files simultaneously.
- Display the number of selected files and their names in a legible list.
- Clearly state the maximum number of permitted files.
const [files, setFiles] = useState<FileList | null>(null);
return (
<FileInput multiple value={files} onChange={(x: FileList | null) => setFiles(x)}>
Choose files
</FileInput>
);
#File Type
When you want to restrict the types of files users can upload (e.g., images only).
Best Practice:
- Specify acceptable file types (e.g., png, jpg)
const [files, setFiles] = useState<FileList | null>(null);
return (
<FileInput
accept=".png, .jpg, .jpeg"
value={files}
onChange={(x: FileList | null) => setFiles(x)}
>
Choose file
</FileInput>
);
#Form Element Wrapper
Integrate the file input seamlessly into forms, aligning with other form elements.
Best Practice:
- Apply consistent styling with other form controls (input fields, buttons, etc.).
- Ensure proper spacing and alignment within the form.
- Provide informative error messages if uploads fail or file types are invalid.
const [files, setFiles] = useState<FileList | null>(null);
const hasFiles = files != undefined && files != null && files.length > 0;
return (
<FormElementWrapper
name="file"
label="Choose File"
error={"Selected file invalid"}
invalid={hasFiles && files[0].size > 1000}
>
<FileInput value={files} onChange={(x: FileList | null) => setFiles(x)}>
<Icon>
<IconAdd />
</Icon>
Add
</FileInput>
</FormElementWrapper>
);
#Variant
Choose the appearance of the file input button to match your design.
Best Practice:
- Prioritize accessibility and maintain clear "button" affordance.
- See Button variant
const [filesPrimary, setFilesPrimary] = useState<FileList | null>(null);
const [filesSecondary, setFilesSecondary] = useState<FileList | null>(null);
const [filesDefault, setFilesDefault] = useState<FileList | null>(null);
const [filesBorderless, setFilesBorderless] = useState<FileList | null>(null);
const [filesCtaPrimary, setFilesCtaPrimary] = useState<FileList | null>(null);
const [filesCtaSecondary, setFilesCtaSecondary] = useState<FileList | null>(null);
const [filesCtaDefault, setFilesCtaDefault] = useState<FileList | null>(null);
return (
<>
<div style={{ display: "block", marginBottom: "1rem" }}>
<FileInput
variant="primary"
value={filesPrimary}
onChange={(x: FileList | null) => setFilesPrimary(x)}
>
Primary
</FileInput>
</div>
<div style={{ display: "block", marginBottom: "1rem" }}>
<FileInput
variant="secondary"
value={filesSecondary}
onChange={(x: FileList | null) => setFilesSecondary(x)}
>
Secondary
</FileInput>
</div>
<div style={{ display: "block", marginBottom: "1rem" }}>
<FileInput value={filesDefault} onChange={(x: FileList | null) => setFilesDefault(x)}>
Default
</FileInput>
</div>
<div style={{ display: "block", marginBottom: "1rem" }}>
<FileInput
variant="borderless"
value={filesBorderless}
onChange={(x: FileList | null) => setFilesBorderless(x)}
>
Borderless
</FileInput>
</div>
<div style={{ display: "block", marginBottom: "1rem" }}>
<FileInput
variant="ctaPrimary"
value={filesCtaPrimary}
onChange={(x: FileList | null) => setFilesCtaPrimary(x)}
>
Primary
</FileInput>
</div>
<div style={{ display: "block", marginBottom: "1rem" }}>
<FileInput
variant="ctaSecondary"
value={filesCtaSecondary}
onChange={(x: FileList | null) => setFilesCtaSecondary(x)}
>
Secondary
</FileInput>
</div>
<div style={{ display: "block", marginBottom: "1rem" }}>
<FileInput
variant="ctaDefault"
value={filesCtaDefault}
onChange={(x: FileList | null) => setFilesCtaDefault(x)}
>
Default
</FileInput>
</div>
</>
);
#Sizes
Adjust the size of the file input to fit different contexts and layouts.
Best Practice:
- Adjust the file input's size for different layouts and screen sizes.
- Maintain visual consistency with other elements.
- Ensure the input is easily clickable on all devices.
const [filesSmall, setFilesSmall] = useState<FileList | null>(null);
const [filesMedium, setFilesMedium] = useState<FileList | null>(null);
const [filesLarge, setFilesLarge] = useState<FileList | null>(null);
return (
<>
<div style={{ display: "block", marginBottom: "1rem" }}>
<FileInput
size="small"
value={filesSmall}
onChange={(x: FileList | null) => setFilesSmall(x)}
>
Small
</FileInput>
</div>
<div style={{ display: "block", marginBottom: "1rem" }}>
<FileInput
size="medium"
value={filesMedium}
onChange={(x: FileList | null) => setFilesMedium(x)}
>
Medium
</FileInput>
</div>
<div style={{ display: "block", marginBottom: "1rem" }}>
<FileInput
size="large"
value={filesLarge}
onChange={(x: FileList | null) => setFilesLarge(x)}
>
Large
</FileInput>
</div>
</>
);
#Full Width
Maximize the width of the file input, especially in wide content areas.
Best Practice:
- Expand the input to the full width of its container.
- Use cautiously, especially on smaller screens.
const [files, setFiles] = useState<FileList | null>(null);
return (
<FileInput fullWidth value={files} onChange={(x: FileList | null) => setFiles(x)}>
Choose file
</FileInput>
);
#Loading
Provide visual feedback while the file is being uploaded. Use Spinner to clearly communicate the upload status to the user.
const [files, setFiles] = useState<FileList | null>(null);
return (
<>
<div style={{ display: "inline-block", marginRight: "0.5rem" }}>
<FileInput loading value={files} onChange={(x: FileList | null) => setFiles(x)}>
Choose file
</FileInput>
</div>
<div style={{ display: "inline-block", marginRight: "0.5rem" }}>
<FileInput
loading
variant="ctaDefault"
value={files}
onChange={(x: FileList | null) => setFiles(x)}
>
Choose file
</FileInput>
</div>
<div style={{ display: "inline-block", marginRight: "0.5rem" }}>
<FileInput loading value={files} onChange={(x: FileList | null) => setFiles(x)}>
<Icon>
<IconAdd />
</Icon>
</FileInput>
</div>
</>
);
#Disabled
Prevent user interaction when the file input is not available.
const [files, setFiles] = useState<FileList | null>(null);
return (
<>
<div style={{ display: "inline-block", marginRight: "0.5rem" }}>
<FileInput disabled value={files} onChange={(x: FileList | null) => setFiles(x)}>
Disabled
</FileInput>
</div>
<div style={{ display: "inline-block", marginRight: "0.5rem" }}>
<FileInput
disabled
variant="ctaDefault"
value={files}
onChange={(x: FileList | null) => setFiles(x)}
>
Disabled
</FileInput>
</div>
<div style={{ display: "inline-block", marginRight: "0.5rem" }}>
<FileInput
disabled
ariaLabel="Add file"
value={files}
onChange={(x: FileList | null) => setFiles(x)}
>
<Icon>
<IconAdd />
</Icon>
</FileInput>
</div>
</>
);
#Properties
Property | Description | Defined | Value |
---|---|---|---|
valueRequired | | object Value of the form control | ||
onChangeRequired | function Callback for onChange event | ||
nameOptional | string Name applied to the form control | ||
idOptional | string Id applied to the form control | ||
invalidOptional | boolean Is the form control invalid | ||
onBlurOptional | function Callback for onBlur event | ||
aria-labelOptional | string Label of the form control | ||
aria-describedbyOptional | string ID of an an element that describes what the form control is for | ||
aria-labelledbyOptional | string ID of an an element that labels this form control | ||
childrenOptional | element Text and icons to be displayed inside the button. | ||
listFilesOptional | boolean Should selected files be listed on screen | ||
hideButtonOptional | boolean Should the button be hidden | ||
multipleOptional | boolean Allow multiple files to be selected | ||
acceptOptional | string Specify accepted file extensions | ||
disabledOptional | boolean Can the file input button be clicked | ||
sizeOptional | "large" | "medium" | "small" Controls the size of the button and listed files - defaults to medium | ||
fullWidthOptional | boolean Should the file input button fill full width? | ||
variantOptional | "borderless" | "ctaDefault" | "ctaPrimary" | "ctaSecondary" | "default" | "destructive" | "primary" | "secondary" How should the file input button look | ||
loadingOptional | boolean Should the file input button show a loading indicator | ||
autoFocusOptional | boolean Focus the file input immediately when rendering the first time | ||
ariaHiddenOptional | boolean Indicates whether the element is exposed to an accessibility API. | ||
ariaLabelOptional | string Describe what happens if the file input is clicked | ||
ariaLabelledByOptional | string ID of an element that describes what happens if the file input is clicked | ||
ariaDescribedByOptional | string IDs of the elements that describe the file input's function | ||
classNameOptional | string Custom className that's applied to the outermost element (only intended for special cases) | ||
styleOptional | object Style object to apply custom inline styles (only intended for special cases) | ||
tabIndexOptional | number Tab index of the outermost HTML element of the component | ||
onKeyDownOptional | function Callback for onKeyDown event | ||
onMouseDownOptional | function Callback for onMouseDown event | ||
onMouseEnterOptional | function Callback for onMouseEnter event | ||
onMouseLeaveOptional | function Callback for onMouseLeave event | ||
onFocusOptional | function Callback for onFocus event | ||
data-componentOptional | string Name of the component. Should only be set by components since it needs to stable. Used to track component usage | ||
data-observe-keyOptional | string Unique string, used by external script e.g. for event tracking |
#Guidelines
#Best practices
#Do not use when
#Accessibility
Explore detailed guidelines for this component: Accessibility Specifications